#include "hashtable.h"
#include <string.h>
#include <algorithm>
#define MAGIC 9979

bool Node::operator!=(const char *str) {
    //TODO
    //重载不等号操作符；如果str与Node里的字符串不一样，则返回true。
    if(str==NULL)return false;
    pair<string,int>tp=(*this->get_pair());
    string this_string=tp.first;
    if(strcmp(str,this_string.c_str())==0)
    {
        return false;
    }
    return true;
}

bool Node::operator!=(const string &str) {
    //TODO
    //重载不等号操作符；如果str与Node里的字符串不一样，则返回true。
    pair<string,int>tp=(*this->get_pair());
    string this_string=tp.first;
    if(str==this_string)
    {
        return false;
    }
    return true;
}

bool Node::operator==(const char *str) {
    //TODO
    //重载等号操作符；如果str与Node里的字符串一样，则返回true。
    if(str==NULL)return false;
    pair<string,int>tp=*this->get_pair();
    string this_string=tp.first;
    if(strcmp(str,this_string.c_str())==0)
    {
        return true;
    }
    return false;
}

bool Node::operator==(const string &str) {
    //TODO
    //重载等号操作符；如果str与Node里的字符串一样，则返回true。
    pair<string,int>tp=(*this->get_pair());
    string this_string=tp.first;
    if(str==this_string)
    {
        return true;
    }
    return false;
}

bool Node::operator!=(Node &n) {
    //TODO
    //重载不等号操作符；如果n与Node里的字符串不一样，则返回true。
    string str1=n.get_pair()->first;
    string str2=this->get_pair()->first;
    if(str1==str2)return false;
    return true;
}

bool Node::operator==(Node &n) {
    //TODO
    //重载等号操作符；如果n与Node里的字符串一样，则返回true。
    string str1=n.get_pair()->first;
    string str2=this->get_pair()->first;
    if(str1==str2)return true;
    return false;
}

char Node::operator[](const int index) {
    //TODO
    //重载方括号[]操作符，返回字符串中下标对应的字符char。
    string str=this->get_pair()->first;
    if(index<0||index>=str.length())return '\0';
    return str[index];
}

int Node::length() { //return length of the string
    //TODO
    //返回字符串的长度。
    string str=this->get_pair()->first;
    return str.length();
}

int &Node::second() {
    //TODO
    //返回pair中第二个元素（就是那个整数型变量）的引用；
    int a=this->get_pair()->second;
    int &b=a;
    return b;
}

const pair<string, int>* Node::get_pair() const {
    //TODO
    //返回一个指向pair的指针；
    return &(this->p);
}

Node::~Node() {
    //TODO
}

HashTable::HashTable() {
    //TODO
    //HashTable的构造函数；建造构造函数，初始化相关变量。
    elem=new Node[MAGIC];
    for(int i=0;i<MAGIC;i++)elem[i].set_next(NULL);
    size=MAGIC;
}

HashTable::~HashTable() {
    //TODO
    //HasnTable的析构函数；你需要清理 HashTable 的所有内存。
    delete []elem;
    elem=NULL;
}

int HashTable::hash(Node &index) {
    //TODO
    //很明显这是一个哈希函数。你需要将一个 Node 对象转为一个整数。
    //这里自己创造一种映射方法
    string str=index.get_pair()->first;
    int h=1;
    for(int i=0;i<str.length();i++)
    {
        h=h*str[i];
    }
    return (h%MAGIC>=0)?h%MAGIC:(h%MAGIC+MAGIC);
}

bool HashTable::search(Node &index, int &pos, int &times) {
    //TODO
    //HashTable的查找函数，如果函数查找index成功，则返回true，否则返回false。
    //pos记录哈希表可插入index的位置，times记录发生冲突的次数。
    int h=hash(index);
    times=0;
    Node *p=elem[h].get_next();
    while (1)
    {
        if(p==NULL)break;
        if(*p==index)
        {
            pos=h;
            return true;
        }
        else
        {
            times++;
        }
        
        p=p->get_next();
    }
    return false;
}

int HashTable::insert(Node &index) {
    //TODO
    //插入一个Node类；如果请求目标存在表中则返回 2。
    //其它情况请返回 1 或 0。（你自行决定，方便你之后 Debug）
    int pos,times;
    if(search(index,pos,times))return 2;
    int h=hash(index);

    return 1;
}

int HashTable::insert(const char * str) {
    //TODO
    return 1;
}

Node* Node::get_next()
{
    return next;
}

void Node::set_next(Node *this_node)
{
    next=this_node;
}

/*
 ==========================================================================
 =================Please Do Not Modify Functions Below=====================
 ========================请不要修改下列函数实现================================
 ==========================================================================
 */

Node::Node() {
    p = make_pair(string("#"), 1);
}

Node::Node(const char *str) {
    p = make_pair(string(str), 1);
}

Node::Node(const string &str) {
    p = make_pair(str, 1);
}

int HashTable::get_size() const {
    return size;
}

const pair<string, int>* HashTable::get_pair(int index) {
    if (index < size && index >= 0) {
        return (elem[index].get_pair());
    }
    return NULL;
}

const pair<string, int>* HashTable::get_pair(int index) const {
    if (index < size && index >= 0) {
        return (elem[index].get_pair());
    }
    return NULL;
}
